﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace snat.model
{

    /// <summary>
    /// Totally not thread-safe at all and is entirely a playground
    /// </summary>
    public class PageRanker
    {
        private int totalGraphSize;
        private int centralGraphSize;
        private Dictionary<int, RankNode> rankNodes = new Dictionary<int,RankNode>();

        private Dictionary<RankNode, double> currentStrength;
        private Dictionary<RankNode, double> nextStrength;


        private int dangleRounds = 0;
        private int coreSize = 0;


        public PageRanker(NetworkModel model) {
            Console.WriteLine("INITIALIZING THING");
            Init(model);
            Console.WriteLine("REMOVING DANGLERS");
            int removed = int.MaxValue;
            while (removed > 0) {
                removed = removeDanglers();
                coreSize += removed;
                dangleRounds++;
                Console.WriteLine("Removed {0} danglers", removed);
            }
            Console.WriteLine("Assigning initial weights");


        }
        public int removeDanglers() {
            int removed = 0;
            foreach (int id in rankNodes.Keys.ToArray()) {
                if (rankNodes[id].IsDangling) {
                    foreach (RankNode node in rankNodes[id].BackwardsNodes) {
                        node.removeDangler(rankNodes[id]);
                        removed++;
                    }
                }
            }
            return removed;
        }




        private void Init(NetworkModel model) {
            totalGraphSize = model.NodeCount;

            
            foreach (BaseNode b in model.Nodes.Values.ToList()) {
                Console.WriteLine("FFs!, {0}", b.ID);
                rankNodes.Add(b.ID, new RankNode(b.ID));
            }

            Console.Write("done that!!!");
            //Now all nodes exist
            foreach (BaseNode b in model.Nodes.Values.ToList()) {

                RankNode corresponding = rankNodes[b.ID];
                foreach (Edge e in b.InEdges) {
                    corresponding.addBackwardsEdge(rankNodes[e.From.ID]);
                }
                foreach (Edge e in b.OutEdges) {
                    corresponding.addForwardsEdge(rankNodes[e.To.ID]);
                }
            }
            //now all edges exist
            currentStrength = new Dictionary<RankNode, double>();
            nextStrength = new Dictionary<RankNode, double>();
        }





        public Dictionary<BaseNode, double> Rank(NetworkModel model) {



            throw new NotImplementedException("bugger off");
        }
    }

    internal class RankNode
    {
        private List<RankNode> backwardNodes = new List<RankNode>();
        public List<RankNode> BackwardsNodes {
            get {
                return backwardNodes;
            }
        }

        private List<RankNode> forwardNodes = new List<RankNode>();
        public List<RankNode> ForwardNodes {
            get {
                return forwardNodes;
            }
        }

        private List<RankNode> forwardDangleNodes = new List<RankNode>();
        public List<RankNode> ForwardDangleNodes {
            get {
                return forwardDangleNodes;
            }
        }

        public readonly int ID;

        public Boolean IsDangling {
            get {
                return (forwardNodes.Count == 0);
            }
        }

        internal RankNode(int _id) {
            ID = _id;
        }

        public void removeDangler(RankNode dangler) {
            forwardNodes.Remove(dangler);
            forwardDangleNodes.Add(dangler);
        }

        public void addForwardsEdge(RankNode forwards) {
            forwardNodes.Add(forwards);
        }
        public void addBackwardsEdge(RankNode backwards) {
            backwardNodes.Add(backwards);
        }

        public void RestoreDanglers() {
            forwardNodes.AddRange(ForwardDangleNodes);
            forwardDangleNodes.Clear();
        }
    }
}
